using AutoMapper;
using Domain.Material_Management;
using Infratructure.Interface;
using MediatR;
using MES.Server.API.Application.Command.Material_Management;
using MES.Server.API.Dto.Material_Management.OutPut;
using ReturnValue;

namespace MES.Server.API.Application.Handler.Material_Management
{
    public class GetBomTreeHandler : IRequestHandler<GetBomTreeCommand, ApiResult<List<GetBomOutPut>>>
    {
        private readonly IRepository<BomModel> bomRepo;
        private readonly IMapper mapper;

        public GetBomTreeHandler(IRepository<BomModel> bomRepo, IMapper mapper)
        {
            this.bomRepo = bomRepo;
            this.mapper = mapper;
        }

        /// <summary>
        /// 获取BOM树形结构
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<ApiResult<List<GetBomOutPut>>> Handle(GetBomTreeCommand request, CancellationToken cancellationToken)
        {
            var result = new ApiResult<List<GetBomOutPut>>();

            List<BomModel> allBoms;

            if (request.RootBomId.HasValue)
            {
                // 获取指定根节点及其所有子节点
                allBoms = GetBomWithChildren(request.RootBomId.Value, request.MaxLevel);
            }
            else
            {
                // 获取所有BOM数据
                allBoms = bomRepo.GetAll().Where(a => !a.IsDel).ToList();
            }

            // 构建树形结构
            var bomTree = BuildBomTree(allBoms, request.RootBomId, request.MaxLevel);

            result.Data = mapper.Map<List<GetBomOutPut>>(bomTree);
            result.Code = StatusCode.Success;
            result.Message = "获取成功！";

            return await Task.FromResult(result);
        }

        /// <summary>
        /// 递归获取BOM及其所有子节点
        /// </summary>
        /// <param name="bomId"></param>
        /// <param name="maxLevel"></param>
        /// <returns></returns>
        private List<BomModel> GetBomWithChildren(long bomId, int? maxLevel)
        {
            var result = new List<BomModel>();
            var rootBom = bomRepo.GetAll().Where(a => a.Id == bomId && !a.IsDel).FirstOrDefault();
            
            if (rootBom == null) return result;

            result.Add(rootBom);

            if (maxLevel.HasValue && rootBom.Level >= maxLevel.Value) return result;

            var children = bomRepo.GetAll().Where(a => a.ParentId == bomId && !a.IsDel).ToList();
            foreach (var child in children)
            {
                result.AddRange(GetBomWithChildren(child.Id, maxLevel));
            }

            return result;
        }

        /// <summary>
        /// 构建BOM树形结构
        /// </summary>
        /// <param name="allBoms"></param>
        /// <param name="rootBomId"></param>
        /// <param name="maxLevel"></param>
        /// <returns></returns>
        private List<BomModel> BuildBomTree(List<BomModel> allBoms, long? rootBomId, int? maxLevel)
        {
            var result = new List<BomModel>();

            // 获取根节点
            List<BomModel> rootNodes;
            if (rootBomId.HasValue)
            {
                rootNodes = allBoms.Where(a => a.Id == rootBomId.Value).ToList();
            }
            else
            {
                rootNodes = allBoms.Where(a => a.ParentId == null || a.ParentId == 0).ToList();
            }

            foreach (var root in rootNodes)
            {
                if (maxLevel.HasValue && root.Level > maxLevel.Value) continue;
                
                root.Children = GetChildren(allBoms, root.Id, maxLevel).ToList();
                result.Add(root);
            }

            return result;
        }

        /// <summary>
        /// 递归获取子节点
        /// </summary>
        /// <param name="allBoms"></param>
        /// <param name="parentId"></param>
        /// <param name="maxLevel"></param>
        /// <returns></returns>
        private IEnumerable<BomModel> GetChildren(List<BomModel> allBoms, long parentId, int? maxLevel)
        {
            var children = allBoms.Where(a => a.ParentId == parentId).ToList();
            
            foreach (var child in children)
            {
                if (maxLevel.HasValue && child.Level >= maxLevel.Value) continue;
                
                child.Children = GetChildren(allBoms, child.Id, maxLevel).ToList();
            }

            return children;
        }
    }
}
